package com.xhs.service;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xhs.dto.SearchNotesResponse;
import com.xhs.dto.XhsApiResponse;
import com.xhs.dto.XhsSearchResponse;
import com.xhs.util.ProxyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 搜索笔记服务
 *
 * @author xhs
 */
@Slf4j
@Service
public class SearchNotesService {

    @Autowired
    private QrCodeDetectionService qrCodeDetectionService;

    @Autowired
    private UserService userService;

    @Autowired
    private ProxyUtil proxyUtil;

    private static final String SEARCH_NOTES_URL = "https://edith.xiaohongshu.com/api/sns/web/v1/search/notes";

    /**
     * 搜索笔记（新版本，支持分页）
     */
    public SearchNotesResponse searchNotes(String phoneNumber, String keyword, Integer page) {
        // 获取cookies字符串
        String cookieString = userService.getCookie(phoneNumber);
        if (cookieString == null || cookieString.isEmpty()) {
            throw new RuntimeException("未找到有效的登录cookies，请先登录");
        }

        // 为本次搜索创建统一的目录名
        String searchDirName = qrCodeDetectionService.createDirectoryName(phoneNumber);
        log.info("本次搜索使用目录: {}", searchDirName);

        List<SearchNotesResponse.ImageInfo> imageInfos = new ArrayList<>();

        log.info("开始搜索第{}页，关键词: {}", page, keyword);

        // 构建请求参数
        Map<String, Object> requestBody = buildSearchRequest(keyword, page);

        // 发送请求
        String response = sendSearchRequest(requestBody, cookieString);

        log.info("第{}页搜索结果: {}", page, response);

        // 检查搜索响应
        if (response == null || response.isEmpty()) {
            throw new RuntimeException("搜索失败，未获取到响应");
        }

        // 解析响应
        JSONObject responseJson = JSONUtil.parseObj(response);

        // 检查小红书API响应状态
        try {
            XhsApiResponse<?> xhsResponse = JSONUtil.toBean(response, XhsApiResponse.class);
            if (!xhsResponse.isSuccess()) {
                // 特殊处理登录态失效的情况
                if (xhsResponse.getCode() != null && xhsResponse.getCode() == -100) {
                    log.warn("登录态失效，清理MySQL中的cookies: phoneNumber={}", phoneNumber);
                    userService.deleteCookie(phoneNumber);
                    throw new RuntimeException("登录态失效，请重新登录");
                }
                log.error("搜索失败，小红书API返回错误: {}", xhsResponse.getErrorMessage());
                throw new RuntimeException("搜索失败: " + xhsResponse.getErrorMessage());
            }
        } catch (Exception e) {
            log.warn("解析搜索响应失败，继续使用原有逻辑: {}", e.getMessage());
            // 检测登录态是否失效（保留原有逻辑作为备用）
            if (responseJson.getInt("code") == -100) {
                log.warn("登录态失效，清理MySQL中的cookies: phoneNumber={}", phoneNumber);
                userService.deleteCookie(phoneNumber);
                throw new RuntimeException("登录态失效，请重新登录");
            }
        }

        // 检测图片中的微信二维码，使用统一的目录名
        imageInfos = detectWechatQrCodesWithDetails(responseJson, phoneNumber, searchDirName);

        SearchNotesResponse searchResponse = new SearchNotesResponse();
        searchResponse.setCurrentPage(page);
        searchResponse.setTotalCount(imageInfos.size());
        searchResponse.setImages(imageInfos);

        log.info("搜索完成，共找到{}个微信二维码图片", imageInfos.size());
        return searchResponse;
    }

    /**
     * 为任务搜索笔记（返回原始响应）
     */
    public String searchNotesForTask(String phoneNumber, String keyword, Integer page) {
        // 获取cookies字符串
        String cookieString = userService.getCookie(phoneNumber);
        if (cookieString == null || cookieString.isEmpty()) {
            throw new RuntimeException("未找到有效的登录cookies，请先登录");
        }

        log.info("为任务搜索第{}页，关键词: {}", page, keyword);

        // 构建请求参数
        Map<String, Object> requestBody = buildSearchRequest(keyword, page);

        // 发送请求
        String response = sendSearchRequest(requestBody, cookieString);

        // 检查搜索响应
        if (response == null || response.isEmpty()) {
            throw new RuntimeException("搜索失败，未获取到响应");
        }

        // 检查小红书API响应状态
        try {
            XhsApiResponse<?> xhsResponse = JSONUtil.toBean(response, XhsApiResponse.class);
            if (!xhsResponse.isSuccess()) {
                // 特殊处理登录态失效的情况
                if (xhsResponse.getCode() != null && xhsResponse.getCode() == -100) {
                    log.warn("登录态失效，清理MySQL中的cookies: phoneNumber={}", phoneNumber);
                    userService.deleteCookie(phoneNumber);
                    throw new RuntimeException("登录态失效，请重新登录");
                }
                log.error("搜索失败，小红书API返回错误: {}", xhsResponse.getErrorMessage());
                throw new RuntimeException("搜索失败: " + xhsResponse.getErrorMessage());
            }
        } catch (Exception e) {
            log.warn("解析搜索响应失败，继续使用原有逻辑: {}", e.getMessage());
            // 检测登录态是否失效（保留原有逻辑作为备用）
            JSONObject responseJson = JSONUtil.parseObj(response);
            if (responseJson.getInt("code") == -100) {
                log.warn("登录态失效，清理MySQL中的cookies: phoneNumber={}", phoneNumber);
                userService.deleteCookie(phoneNumber);
                throw new RuntimeException("登录态失效，请重新登录");
            }
        }

        return response;
    }

    /**
     * 搜索笔记（旧版本，保持兼容性）
     */
    public List<String> searchNotes(String phoneNumber, String keyword) {
        // 获取cookies字符串
        String cookieString = userService.getCookie(phoneNumber);
        if (cookieString == null || cookieString.isEmpty()) {
            throw new RuntimeException("未找到有效的登录cookies，请先登录");
        }

        // 为本次搜索创建统一的目录名
        String searchDirName = qrCodeDetectionService.createDirectoryName(phoneNumber);
        log.info("本次搜索使用目录: {}", searchDirName);

        List<String> wechatQrCodeImages = new ArrayList<>();

        // 循环调用5次，页数从1到5
        for (int page = 1; page <= 5; page++) {
            try {
                log.info("开始搜索第{}页，关键词: {}", page, keyword);

                // 构建请求参数
                Map<String, Object> requestBody = buildSearchRequest(keyword, page);

                // 发送请求
                String response = sendSearchRequest(requestBody, cookieString);

                log.info("第{}页搜索结果: {}", page, response);

                // 检查搜索响应
                if (response == null || response.isEmpty()) {
                    throw new RuntimeException("搜索失败，未获取到响应");
                }

                // 解析响应
                JSONObject responseJson = JSONUtil.parseObj(response);

                // 检查小红书API响应状态
                try {
                    XhsApiResponse<?> xhsResponse = JSONUtil.toBean(response, XhsApiResponse.class);
                    if (!xhsResponse.isSuccess()) {
                        // 特殊处理登录态失效的情况
                        if (xhsResponse.getCode() != null && xhsResponse.getCode() == -100) {
                            log.warn("登录态失效，清理MySQL中的cookies: phoneNumber={}", phoneNumber);
                            userService.deleteCookie(phoneNumber);
                            throw new RuntimeException("登录态失效，请重新登录");
                        }
                        log.error("搜索失败，小红书API返回错误: {}", xhsResponse.getErrorMessage());
                        throw new RuntimeException("搜索失败: " + xhsResponse.getErrorMessage());
                    }
                } catch (Exception e) {
                    log.warn("解析搜索响应失败，继续使用原有逻辑: {}", e.getMessage());
                    // 检测登录态是否失效（保留原有逻辑作为备用）
                    if (responseJson.getInt("code") == -100) {
                        log.warn("登录态失效，清理MySQL中的cookies: phoneNumber={}", phoneNumber);
                        userService.deleteCookie(phoneNumber);
                        throw new RuntimeException("登录态失效，请重新登录");
                    }
                }

                // 检测图片中的微信二维码，使用统一的目录名
                List<String> pageQrImages = detectWechatQrCodes(responseJson, phoneNumber, searchDirName);
                wechatQrCodeImages.addAll(pageQrImages);

                // 等待一秒避免请求过快
                Thread.sleep(1000);

            } catch (Exception e) {
                log.error("搜索第{}页失败", page, e);
            }
        }

        log.info("搜索完成，共找到{}个微信二维码图片", wechatQrCodeImages.size());
        return wechatQrCodeImages;
    }

    /**
     * 构建搜索请求参数
     */
    private Map<String, Object> buildSearchRequest(String keyword, int page) {
        Map<String, Object> request = new HashMap<>();
        request.put("keyword", keyword);
        request.put("page", page);
        request.put("page_size", 20);
        request.put("search_id", RandomUtil.randomString(21) + "@" + RandomUtil.randomString(21));
//        request.put("search_id", "2f1jxbw64741b4jcumh46@2f1jxdfpmnba1p9b81p88");
        request.put("sort", "time_descending");
        request.put("note_type", 0);
        request.put("ext_flags", new ArrayList<>());

        // 构建 filters
        List<Map<String, Object>> filters = new ArrayList<>();

        Map<String, Object> sortFilter = new HashMap<>();
        sortFilter.put("tags", List.of("time_descending"));
        sortFilter.put("type", "sort_type");
        filters.add(sortFilter);

        Map<String, Object> noteTypeFilter = new HashMap<>();
        noteTypeFilter.put("tags", List.of("不限"));
        noteTypeFilter.put("type", "filter_note_type");
        filters.add(noteTypeFilter);

        Map<String, Object> timeFilter = new HashMap<>();
        timeFilter.put("tags", List.of("不限"));
        timeFilter.put("type", "filter_note_time");
        filters.add(timeFilter);

        Map<String, Object> rangeFilter = new HashMap<>();
        rangeFilter.put("tags", List.of("不限"));
        rangeFilter.put("type", "filter_note_range");
        filters.add(rangeFilter);

        Map<String, Object> distanceFilter = new HashMap<>();
        distanceFilter.put("tags", List.of("不限"));
        distanceFilter.put("type", "filter_pos_distance");
        filters.add(distanceFilter);

        request.put("filters", filters);
        request.put("geo", "");
        request.put("image_formats", List.of("jpg", "webp", "avif"));

        return request;
    }

    /**
     * 发送搜索请求
     */
    private String sendSearchRequest(Map<String, Object> requestBody, String cookieString) {
        HttpRequest request = HttpRequest.post(SEARCH_NOTES_URL)
                .header("Content-Type", "application/json")
                .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
                .header("Referer", "https://www.xiaohongshu.com/")
                .header("Origin", "https://www.xiaohongshu.com");

        // 设置代理
        request = proxyUtil.setProxy(request);

        // 设置 cookies
        request.header("Cookie", cookieString);

        // 设置请求体
        String jsonBody = JSONUtil.toJsonStr(requestBody);
        request.body(jsonBody);

        HttpResponse response = request.execute();
        return response.body();
    }

    /**
     * 检测响应中的微信二维码（新版本，返回详细信息）
     */
    private List<SearchNotesResponse.ImageInfo> detectWechatQrCodesWithDetails(JSONObject responseJson, String phoneNumber, String searchDirName) {
        List<SearchNotesResponse.ImageInfo> imageInfos = new ArrayList<>();

        // 使用HuTool直接转换为Java Bean
        XhsSearchResponse searchResponse = JSONUtil.toBean(responseJson, XhsSearchResponse.class);
        if (searchResponse == null || searchResponse.getData() == null) {
            return imageInfos;
        }

        List<XhsSearchResponse.ItemInfo> items = searchResponse.getData().getItems();
        if (items == null || items.isEmpty()) {
            return imageInfos;
        }

        for (int i = 0; i < items.size(); i++) {
            XhsSearchResponse.ItemInfo item = items.get(i);
            XhsSearchResponse.NoteCard noteCard = item.getNote_card();
            if (noteCard == null) {
                continue;
            }

            // 获取笔记信息
            String displayTitle = noteCard.getDisplay_title();
            String noteId = item.getId();
            if (StrUtil.isBlank(displayTitle)) {
                displayTitle = "untitled_" + i;
            }

            // 清理标题，去除特殊字符
            String cleanTitle = cleanFileName(displayTitle);

            // 检查图片列表，只取每个info_list的第一个元素
            List<XhsSearchResponse.ImageInfo> imageList = noteCard.getImage_list();
            if (imageList != null) {
                for (int j = 0; j < imageList.size(); j++) {
                    XhsSearchResponse.ImageInfo image = imageList.get(j);

                    // 只检查 info_list 的第一个元素
                    List<XhsSearchResponse.ImageDetailInfo> infoList = image.getInfo_list();
                    if (infoList != null && !infoList.isEmpty()) {
                        XhsSearchResponse.ImageDetailInfo firstInfo = infoList.get(0);
                        String imageUrl = firstInfo.getUrl();
                        if (StrUtil.isNotBlank(imageUrl)) {
                            // 生成文件名：标题 + 序号
                            String fileName = cleanTitle + "_" + (j + 1);
                            
                            // 检查是否是微信二维码
                            if (qrCodeDetectionService.isWechatQrCode(imageUrl)) {
                                // 下载图片
                                String localPath = qrCodeDetectionService.downloadWechatQrCodeImageWithDir(imageUrl, phoneNumber, fileName, searchDirName);
                                
                                // 创建图片信息
                                SearchNotesResponse.ImageInfo imageInfo = new SearchNotesResponse.ImageInfo();
                                imageInfo.setImageUrl(imageUrl);
                                imageInfo.setLocalPath(localPath);
                                imageInfo.setNoteTitle(displayTitle);
                                imageInfo.setNoteId(noteId);
                                
                                imageInfos.add(imageInfo);
                                log.info("发现微信二维码图片: {}, 文件名: {}, 手机号: {}, 目录: {}", imageUrl, fileName, phoneNumber, searchDirName);
                            }
                        }
                    }
                }
            }
        }

        return imageInfos;
    }

    /**
     * 检测响应中的微信二维码（旧版本，保持兼容性）
     */
    private List<String> detectWechatQrCodes(JSONObject responseJson, String phoneNumber, String searchDirName) {
        List<String> wechatQrImages = new ArrayList<>();

        try {
            JSONObject data = responseJson.getJSONObject("data");
            if (data == null) {
                return wechatQrImages;
            }

            JSONArray items = data.getJSONArray("items");
            if (items == null) {
                return wechatQrImages;
            }

            for (int i = 0; i < items.size(); i++) {
                JSONObject item = items.getJSONObject(i);
                JSONObject noteCard = item.getJSONObject("note_card");
                if (noteCard == null) {
                    continue;
                }

                // 获取标题，用于文件命名
                String displayTitle = noteCard.getStr("display_title");
                if (StrUtil.isBlank(displayTitle)) {
                    displayTitle = "untitled_" + i;
                }

                // 清理标题，去除特殊字符
                String cleanTitle = cleanFileName(displayTitle);

                // 检查图片列表，只取每个info_list的第一个元素
                JSONArray imageList = noteCard.getJSONArray("image_list");
                if (imageList != null) {
                    for (int j = 0; j < imageList.size(); j++) {
                        JSONObject image = imageList.getJSONObject(j);

                        // 只检查 info_list 的第一个元素
                        JSONArray infoList = image.getJSONArray("info_list");
                        if (infoList != null && infoList.size() > 0) {
                            JSONObject firstInfo = infoList.getJSONObject(0);
                            String imageUrl = firstInfo.getStr("url");
                            if (StrUtil.isNotBlank(imageUrl)) {
                                // 生成文件名：标题 + 序号
                                String fileName = cleanTitle + "_" + (j + 1);
                                checkAndDownloadQrCode(imageUrl, fileName, wechatQrImages, phoneNumber, searchDirName);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("检测微信二维码失败", e);
        }

        return wechatQrImages;
    }

    /**
     * 检查并下载微信二维码
     */
    private void checkAndDownloadQrCode(String imageUrl, String fileName, List<String> wechatQrImages, String phoneNumber, String searchDirName) {
        try {
            if (qrCodeDetectionService.isWechatQrCode(imageUrl)) {
                wechatQrImages.add(imageUrl);
                String localPath = qrCodeDetectionService.downloadWechatQrCodeImageWithDir(imageUrl, phoneNumber, fileName, searchDirName);
                log.info("发现微信二维码图片: {}, 文件名: {}, 手机号: {}, 目录: {}, 本地路径: {}", imageUrl, fileName, phoneNumber, searchDirName, localPath);
            }
        } catch (Exception e) {
            log.error("检查微信二维码失败: {}, 文件名: {}, 手机号: {}, 目录: {}", imageUrl, fileName, phoneNumber, searchDirName, e);
        }
    }

    /**
     * 清理文件名，移除特殊字符
     */
    private String cleanFileName(String title) {
        if (StrUtil.isBlank(title)) {
            return "untitled";
        }

        // 移除或替换特殊字符
        String cleaned = title.replaceAll("[\\\\/:*?\"<>|]", "_")
                .replaceAll("\\s+", "_")
                .replaceAll("_+", "_")
                .trim();

        // 限制长度
        if (cleaned.length() > 50) {
            cleaned = cleaned.substring(0, 50);
        }

        // 确保不以点开头或结尾
        cleaned = cleaned.replaceAll("^\\.|\\.$", "_");

        return StrUtil.isBlank(cleaned) ? "untitled" : cleaned;
    }
} 